/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import type.PaymentMethod;

/**
 *
 * @author edd
 */
@Entity(name = "PurchaseOrder")
public class PurchaseOrderEntity extends DataObjectEntity implements Serializable {
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date preferredLeadTime;
    private PaymentMethod paymentMethod;
    private AddressEntity billingAddress;
    private boolean partialDelivery;
    private Collection<String> serviceRequests = new ArrayList<String>();
    
    @OneToMany(cascade={CascadeType.ALL}, mappedBy="purchaseOrder")
    private Collection<ShippingRequestEntity> shippingRequests = new ArrayList<ShippingRequestEntity>();
    
    @OneToMany(cascade={CascadeType.ALL}, mappedBy = "purchaseOrder")
    private Collection<ProductQuantityPriceEntity> productQuantityPrice = new ArrayList<ProductQuantityPriceEntity>();
    
    @ManyToOne
    private SalesQuotationEntity salesQuotation;
    
    @OneToOne
    private SalesOrderEntity salesOrder;
    
    @ManyToOne
    private SalesLeadEntity salesLead;
    
    @ManyToOne
    private CustomerEntity customer;
    
    @ManyToOne
    private SystemUserEntity systemUser;
    
    public PurchaseOrderEntity() {
        super(); 
    }
    
    public boolean isPartialDelivery() {
        return partialDelivery;
    }

    public void setPartialDelivery(boolean partialDelivery) {
        this.partialDelivery = partialDelivery;
    }

    public SalesQuotationEntity getSalesQuotation() {
        return salesQuotation;
    }

    public void setSalesQuotation(SalesQuotationEntity salesQuotation) {
        this.salesQuotation = salesQuotation;
    }

    public SalesOrderEntity getSalesOrder() {
        return salesOrder;
    }

    public void setSalesOrder(SalesOrderEntity salesOrder) {
        this.salesOrder = salesOrder;
    }

    public CustomerEntity getCustomer() {
        return customer;
    }

    public void setCustomer(CustomerEntity customer) {
        this.customer = customer;
    }

    public PaymentMethod getPaymentMethod() {
        return paymentMethod;
    }

    public void setPaymentMethod(PaymentMethod paymentMethod) {
        this.paymentMethod = paymentMethod;
    }

    public Collection<ProductQuantityPriceEntity> getProductQuantityPrice() {
        return productQuantityPrice;
    }

    public void setProductQuantityPrice(Collection<ProductQuantityPriceEntity> productQuantityPrice) {
        this.productQuantityPrice = productQuantityPrice;
    }

    public Collection<ShippingRequestEntity> getShippingRequests() {
        return shippingRequests;
    }

    public void setShippingRequests(Collection<ShippingRequestEntity> shippingRequests) {
        this.shippingRequests = shippingRequests;
    }

    public Date getPreferredLeadTime() {
        return preferredLeadTime;
    }

    public void setPreferredLeadTime(Date preferredLeadTime) {
        this.preferredLeadTime = preferredLeadTime;
    }

    public SalesLeadEntity getSalesLead() {
        return salesLead;
    }

    public void setSalesLead(SalesLeadEntity salesLead) {
        this.salesLead = salesLead;
    }

    public SystemUserEntity getSystemUser() {
        return systemUser;
    }

    public void setSystemUser(SystemUserEntity systemUser) {
        this.systemUser = systemUser;
    }

    public AddressEntity getBillingAddress() {
        return billingAddress;
    }

    public void setBillingAddress(AddressEntity billingAddress) {
        this.billingAddress = billingAddress;
    }
    
    public double getTotalPrice(){
        double total = 0;
        for(ProductQuantityPriceEntity pgp : productQuantityPrice){
            total += pgp.getPrice();
        }        
        return total;
    }
    
    public HashMap<ProductEntity, Double> getProductToUnitPriceHash(){
        HashMap<ProductEntity, Double> productToUnitPrice = new HashMap<ProductEntity, Double>();
        for(ProductQuantityPriceEntity pqp : productQuantityPrice){
            productToUnitPrice.put(pqp.getProduct(), pqp.getPricePerUnit());
        }
        return productToUnitPrice;
    }
    
    @Override
    public String childToString() {
        return "PurchaseOrderEntity{" + "preferredLeadTime=" + preferredLeadTime + ", paymentMethod=" + paymentMethod + ", billingAddress=" + billingAddress + ", partialDelivery=" + partialDelivery + ", shippingRequests=" + shippingRequests + ", productQuantityPrice=" + productQuantityPrice + ", salesQuotation=" + salesQuotation + ", salesOrder=" + salesOrder + ", salesLead=" + salesLead + ", customer=" + customer + ", systemUser=" + systemUser + '}';
    }

    public Collection<String> getServiceRequests() {
        return serviceRequests;
    }

    public void setServiceRequests(Collection<String> serviceRequests) {
        this.serviceRequests = serviceRequests;
    }
    
    public HashMap<CompletedGoodsEntity, Long> getProductToQuantityAggByShippingRequest(){
        HashMap<CompletedGoodsEntity, Long> goodsToQuantity = new HashMap<CompletedGoodsEntity, Long>();
        
        for(ShippingRequestEntity request : shippingRequests){
            Long q = goodsToQuantity.get(request.getProduct());
            if(q==null){
                q=0L;
            }
            goodsToQuantity.put((CompletedGoodsEntity)request.getProduct(), q+request.getQuantity());           
        }
        
        return goodsToQuantity;
    }
    
    public ArrayList<CompletedGoodsEntity> getMismatchedPqpAndShippingRequest(){
        ArrayList<CompletedGoodsEntity> mismatch = new ArrayList<CompletedGoodsEntity>();
        HashMap<CompletedGoodsEntity, Long> goodsToQuantity = getProductToQuantityAggByShippingRequest();
        for(ProductQuantityPriceEntity pqp : productQuantityPrice){
            Long shippingTotal = goodsToQuantity.get(pqp.getProduct());
            if(shippingTotal==null){
                if(pqp.getQuantity()!=0)
                    mismatch.add((CompletedGoodsEntity)pqp.getProduct());
            }
            else if(!shippingTotal.equals(pqp.getQuantity())){
                mismatch.add((CompletedGoodsEntity)pqp.getProduct());
            }
        }
        return mismatch;
    }
    
    public HashSet<CompletedGoodsEntity> getGoodsHash(){
        HashSet<CompletedGoodsEntity> goodsHash = new HashSet<CompletedGoodsEntity>();
        for(ProductQuantityPriceEntity pqp : productQuantityPrice){
            goodsHash.add((CompletedGoodsEntity)pqp.getProduct());
        }
        return goodsHash;
    }
    
    public ProductQuantityPriceEntity findPqp(CompletedGoodsEntity goods){
        ProductQuantityPriceEntity resPqp = null;
        for(ProductQuantityPriceEntity pqp : productQuantityPrice){
            if(pqp.getProduct().equals(goods)){
                resPqp = pqp;
                break;
            }
        }
        
        return resPqp;
    }
    
    public void addPqp(ProductQuantityPriceEntity newPqp){
        HashSet<CompletedGoodsEntity> pqpHash = getGoodsHash();
        if(pqpHash.contains(newPqp.getProduct())){
            findPqp((CompletedGoodsEntity)newPqp.getProduct()).setQuantity(newPqp.getQuantity());
        }
        else{
            newPqp.setPurchaseOrder(this);
            getProductQuantityPrice().add(newPqp);
        }
    }
}
